﻿using System.Linq;
using Coder.Workflow;
using Coder.Workflow.Searcher;
using Coder.Workflow.ViewModel;
using Fee;
using Fee.Orders;
using Fee.Orders.PreWorkflow;
using Fee.Orders.ViewModel;
using Fee.Searchers;
using Fee.Stores;
using Identity;
using JwtWebApi.Filters;
using JwtWebApi.Models.ViewModel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace JwtWebApi.Models.WorkflowController
{
    [Authorize]
    [Route("[controller]")]
    [ApiController]
    [EnableCors]
    public class WorkActivityControllerBase<T, TOrder, TOrderStore, TOrderManager> : Controller
        where T : FeeDbContext
        where TOrder : DelegateOrderBase
        where TOrderStore : IOrderStore<T, TOrder>
        where TOrderManager : WorkflowManager<T, TOrder>
    {
        private readonly T _context;
        private readonly TOrderStore _delegateOrderStore;
        private readonly TOrderManager _workflowManager;

        public WorkActivityControllerBase(TOrderManager workflowManager,
            T context, TOrderStore delegateOrderStore)
        {
            _workflowManager = workflowManager;
            _context = context;
            _delegateOrderStore = delegateOrderStore;
        }

        [HttpGet("list")]
        public IActionResult List([FromQuery] DelegateOrderSearch searcher)
        {
            var query = _delegateOrderStore.List(searcher, out var total);
            return Json(new
            {
                total,
                data = query
            });
        }


        [HttpGet("work-activity/{id:int}")]
        public IActionResult GetTask(int id)
        {
            var workflowInstanceItem = _workflowManager.GetWorkActivity(id, true);

            var r = new WorkActivityViewData<OrderViewModel>(workflowInstanceItem);
            r.ProcessInstance = new OrderViewModel((DelegateOrderBase) workflowInstanceItem.ProcessInstance);
            return Json(r);
        }


        [HttpPost("reject/{id:int}")]
        [ModelValidteFilter]
        public IActionResult Reject([FromRoute] int id, [FromBody] WorkflowDepositViewModel model)
        {
            _workflowManager.Reject(id, model.Comment, out var workActivities);
            return Json(new
            {
                successed = true,
                message = "已经退回"
            });
        }

        [HttpPost("resolve/{id:int}")]
        [ModelValidteFilter]
        public IActionResult Resolve([FromRoute] int id, [FromBody] WorkflowDepositViewModel model)
        {
            _workflowManager.Resolve(id, model.Comment, out var workActivities);
            return Json(new
            {
                successed = true,
                message = "处理成功"
            });
        }


        [HttpGet("get/{id:int}")]
        public IActionResult Get([FromRoute] int id)
        {
            var result = _delegateOrderStore.GetById(id);
            return Json(new OrderViewModel(result));
        }

        [HttpGet("myTask")]
        public IActionResult GetMyTask([FromQuery] WorkActivitySearcher searcher)
        {
            var roleids = searcher.Roles.Select(f => f.Id);


            var query = _context.WorkActivities
                .Where(f =>
                    (roleids.Contains(f.Role.Id) || searcher.UserId == f.DepositUser.Id ||
                     roleids.Contains(_context.AdminRoleId()))
                    && (searcher.Statuses == null || searcher.Statuses.Contains(f.Status)
                        && f.ProcessInstance.WorkProcess.WorkflowType == PreDelegateOrder.WorkFlowType
                    )
                );

            var total = query.Count();
            var dataQuery = query
                    .Include(f => f.DepositUser)
                    .Include(f => f.ProcessInstance)
                    .ThenInclude(f => f.User)
                    .Include(f => f.ProcessInstance)
                    .ThenInclude(f => f.WorkProcess)
                    .Include(f => (PreDelegateOrder) f.ProcessInstance)
                    .ThenInclude(f => f.ConstructionTask)
                    .ThenInclude(f => f.Station)
                    .ThenInclude(f => f.District)
                    .Include(f => (PreDelegateOrder) f.ProcessInstance)
                    .Skip(searcher.GetSkip()).Take(searcher.GetTake())
                ;


            return Json(new
            {
                data = dataQuery.ToList(),
                total
            });
        }
    }
}